import BaseClass from "../base/BaseClass"
import Log from "../utils/Log"
import State from "./State"
import Dictionary from "../utils/Dictionary"
/**
 * 状态机
 */
export default class StateMachine extends BaseClass<StateMachine> {

	/** 初始化的状态 */
	public static InvalidState: string = "Invalid";
	/** 记录所有状态 */
	protected s_Dic: Dictionary // Map<string, State> 可以考虑后期改为map的实现
	/** 现在的状态 */
	protected s_now: State = null;
	/** 上一个状态 */
	protected s_last: State = null;
	/** 全局的状态 */
	protected s_global: State = null;
	/** 状态持有者 */
	protected _owner: Object

	constructor(owner: Object) {
		super()
		this.s_Dic = new Dictionary()
		this._owner = owner
	}

	public isExist(Key: string): boolean { return this.s_Dic.has(Key) }

	public getStateByKey(Key: string): State { return this.s_Dic.get(Key) }

	public setOwner(owner: Object): void { this._owner = owner }

	public getOwner(): Object { return this._owner }

	/**
	 * 注册状态 
	 * @param key
	 * @param state
	 * 
	 */
	public registerState(state: State): void {
		if (this._owner != state.owner) {
			Log.trace("statemachine 与 state 所有者不一致")
			return
		}
		let key: string = cc.js.getClassName(state)
		Log.info(key)
		this.s_Dic.add(key, state)
	}
	/**
	 * 设置全局状态
	 * @param state 
	 * @param obj 
	 */
	public setGlobalState(state: State, obj: Object = null): void {
		this.s_global = state
		this.s_global.onEnter(obj)
	}

	/**
	 * 移除状态 
	 * @param key
	 */
	public removeState(key: string): void { this.s_Dic.del(key) }

	/**
	 * 改变状态 
	 * @param key 变为哪个状态
	 * @param obj
	 */
	public changeState(key: string, obj: Object = null): void {
		let newState: State = this.s_Dic.get(key)
		if (newState == null) {
			Log.error("unregister state type: " + key)
			return
		}
		// 如果状态改变后未变化，则不用理
		if (this.s_now != null && this.s_last != null &&
			this.s_now.getStateKey() == this.s_last.getStateKey()) {
			return
		}
		// 当前状态结束，变为另一个状态
		if (this.s_now != null) { this.s_now.onLeave(newState.getStateKey()) }

		this.s_last = this.s_now
		this.s_now = newState
		// 如果新的状态还未初始化，就初始化一下
		if (!this.s_now.inited) { this.s_now.onInit(obj) }
		this.s_now.onEnter(obj)
	}
	/**
	 * 再次进入状态
	 * @param obj 
	 */
	public reEnterState(obj: Object = null): void {
		if (this.s_now) { this.s_now.onReEnter(obj) }
	}

	/**
	 * 更新状态情况
	 */
	public update(): void {
		if (this.s_global != null) { this.s_global.onUpdate() }
		if (this.s_now != null) { this.s_now.onUpdate() }
	}

	/**
	 * 当前状态类型  
	 * @return
	 */
	public getCurrentState(): string {
		if (this.s_now != null) { return this.s_now.getStateKey() }
		return StateMachine.InvalidState
	}

	/**
	 * 清除
	 */
	public clear(): void {
		if (this.s_now != null)
			this.s_now.onLeave(StateMachine.InvalidState)
		this.s_Dic.clear()
		this.s_now = null
		this.s_last = null
	}
}